/*
 * DialogNewGame
 * Version: 0.1
 * Date: 2009-03-01
 * Author: gp08-nhn
 */

package keyboardhero;

import java.awt.*;
import java.awt.event.*;
import java.net.URL;

import javax.swing.*;
import keyboardhero.DialogSongList.*;
import keyboardhero.Util.*;

final class DialogNewGame extends AbstractDialog {
	
	//-------------------- VARIABLES --------------------
	
	private static final long serialVersionUID = -5547093721008793310L;
	
	private static DialogNewGame instance = null;
	private SongSelector songSelector;
	private JComboBox speedList = null;
	private static final float[] SPEEDS = new float[] {0.2f, 0.25f, 0.35f, 0.5f, 0.65f, 0.75f, 0.9f, 1, 1.1f, 1.25f, 1.5f, 2, 3, 4, 5};
	private static Runnable action;
	
	//-------------------- CORE FUNCTIONS --------------------
	
	public DialogNewGame(JFrame frame) {
		super(frame, "Menu_NewGame", "newGame", false, true, action = new Runnable() {
			public void run() {
				final URL file = instance.songSelector.getSelectedFile();
				if(file == null) {
					Util.warning(Util.getMsg("Wrn_SelectFile"));
				} else {
					instance.close();
					Game.newGame(file, instance.getSpeed());
				}
			}
		});
		
		JPanel panel, spanel;
		Container contentPane;
		
		(contentPane = getContentPane()).add(songSelector = new SongSelector(configKey, action));
		
		contentPane.add(panel = new JPanel(), BorderLayout.SOUTH);
		panel.setLayout(new BorderLayout());
		
		panel.add(spanel = new JPanel(), BorderLayout.WEST);
		spanel.setLayout(new FlowLayout());
		
		speedList = new JComboBox();
		
		int i = 0;
		boolean notSet = true;
		boolean defSet = false;
		int def = 0;
		final float factor = Util.getPropFloat("speed", 1.0f);
		for(float speed : SPEEDS) {
			speedList.addItem(new Item<Float, String>(speed, Util.floatToSpeed(speed)));
			if(factor == speed) {
				notSet = false;
				speedList.setSelectedIndex(i);
			} else if(factor == 1.0f) {
				defSet = true;
				def = i;
			}
			++i;
		}
		
		if(notSet && defSet) {
			speedList.setSelectedIndex(def);
		}
		
		final JLabel label;
		spanel.add(label = new JLabel(Util.getMsgMnemonic("LabelSpeed")));
		label.setName("LabelSpeed");
		label.setLabelFor(speedList);
		label.setDisplayedMnemonic(Util.getLastMnemonic());
		label.setDisplayedMnemonicIndex(Util.getLastMnemonicIndex());
		label.addMouseListener(Util.LABEL_MOUSE_LISTENER);
		
		spanel.add(speedList);
		
		panel.add(spanel = new JPanel(), BorderLayout.CENTER);
		spanel.setLayout(new FlowLayout());
		
		JButton bnOk;
		spanel.add(bnOk = new JButton(Util.getMsgMnemonic("OK")));
		bnOk.setMnemonic(Util.getLastMnemonic());
		bnOk.setDisplayedMnemonicIndex(Util.getLastMnemonicIndex());
		bnOk.setName("OK");
		bnOk.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				action.run();
			} // end method
		} // end class
		);
		
		JButton bnCancel;
		spanel.add(bnCancel = new JButton(Util.getMsgMnemonic("Cancel")));
		bnCancel.setMnemonic(Util.getLastMnemonic());
		bnCancel.setDisplayedMnemonicIndex(Util.getLastMnemonicIndex());
		bnCancel.setName("Cancel");
		bnCancel.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				close();
			} // end method
		} // end class
		);
		
		panel.add(spanel = new JPanel(), BorderLayout.EAST);
		
		JButton bnRefresh;
		spanel.add(bnRefresh = new JButton());
		Util.updateButtonText(bnRefresh, "Refresh");
		bnRefresh.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				SongSelector.refresh();
			} // end method
		} // end class
		);
		
		getRootPane().setDefaultButton(bnOk);
		
		instance = this;
	}
	
	@SuppressWarnings("unchecked")
	final float getSpeed() {
		final Item<Float, String> item = (Item<Float, String>)speedList.getSelectedItem();
		if(item == null) return 1.0f;
		return item.getKey();
	}
	
	//-------------------- OVERRIDING FUNCTIONS --------------------
	
	@Override
	protected void closure() {
		if(wasOpened) {
			super.closure();
			songSelector.closure();
			Util.setProp("speed", getSpeed());
		}
	}
	
	@Override
	protected AbstractDialog getNewInstance(JFrame frame) {
		return new DialogNewGame(frame);
	}
	
	//-------------------- DEBUGGING FUNCTIONS --------------------
	
	/**
	 * Creates a string containing the most important information about the
	 * {@link DialogNewGame#instance main DialogToplist} object. This method is used only for
	 * debugging and testing purposes.
	 * 
	 * @return the created string.
	 */
	static String getString() {
		return "DialogNewGame(visible=" + instance.isVisible() + "; location=" + instance.getLocationOnScreen() + "; bounds=" + instance.getBounds() + ")";
	} // end method
	
	/**
	 * This method serves security purposes. Provides an integrity string that will be checked by
	 * the {@link Connection#integrityCheck()} method; thus the application can only be altered if
	 * the source is known. Every class in the {@link keyboardhero} package has an integrity string.
	 * 
	 * @return the string of this class used for integrity checking.
	 */
	static String getIntegrityString() {
		return "sdfDg!+%asÉ\tjfg ash";
	} // end method
	
	/**
	 * The tester object of this class. It provides a debugging menu and unit tests for this class.
	 * Its only purpose is debugging or testing.
	 */
	final static Tester TESTER = new Tester("DialogNewGame", new String[] {"getString()"} /* end initialization */) { //$SUP-PPA$
		void menu(int choice) throws Exception {
			switch(choice) {
				case 5:
					System.out.println(getString());
					break;
				default:
					baseMenu(choice);
					break;
			} // end switch
		} // end method
		
		void runUnitTests() throws Exception {
			higherTestStart("DialogNewGame");
			
			testEq("getIntegrityString()", "sdfDg!+%asÉ\tjfg ash", DialogNewGame.getIntegrityString());
			
			higherTestEnd();
		} // end method
	}; // end class
	
	/**
	 * Starts the class's developing menu. If this build is a developer's one it starts the
	 * application in a normal way with the exception that it starts the debugging tool for this
	 * class as well; otherwise exits with an error message.
	 * 
	 * @param args
	 *            the arguments given to the program.
	 * @see KeyboardHero#startApp()
	 */
	public static void main(String[] args) {
		Tester.mainer(args, TESTER);
	} // end method
}
